﻿#include <iostream>
#include "../EasyxToolsHeaderFile/Table.h"

Table::Table(int row, int column)
//初始化父类
        : BasicWidget(0, 0, 0, 0), m_rows(row), m_cols(column),/*分页处理变量初始化*/ m_currentPage(0), m_maxPage(0),
          m_extraData(0) {
    m_previousBtn.setBtnText("上一页");
    m_nextBtn.setBtnText("下一页");
    m_firstBtn.setBtnText("第一页");
    m_lastBtn.setBtnText("末尾页");
}

/*//释放内存，避免内存泄露
Table::~Table() {
    *//*  delete在对象上使用运算符将释放其内存，当 delete 使用释放 c + + 类对象的内存时，
     * 将在释放对象的内存之前调用对象的析构函数 (如果对象具有析构函数) 。*//*
    delete m_previousBtn;
    delete m_nextBtn;
    delete m_firstBtn;
    delete m_lastBtn;
}*/

void Table::setRow(int row) {
    m_rows = row;
}

void Table::setColumn(int column) {
    m_cols = column;
}

void Table::show() {
    drawTableGrid();
    drawTableData();
}

void Table::setHeader(const std::string &header) {
    m_headName = header;
    //获取列数
    m_cols = std::count(m_headName.begin(), m_headName.end(), '\t') + 1;
    //文字的宽度和高度
    m_tW = ::textwidth("计算机科学与技术") - 15;
    m_tH = ::textheight(m_headName.c_str());
    //获取格子的宽度和高度
    m_gridW = m_tW + 10;
    m_gridH = m_tH + 15;
    //获取表格的宽度和高度
    m_w = m_gridW * m_cols;
    m_h = m_gridH * (m_rows + 1);
}

void Table::drawTableHeader() {
    /*设置表头风格---加粗*/
    setlinestyle(PS_SOLID, 3); //PS_SOLID 线形为实线，thickness为线的宽度，以像素为单位。
    /*画无填充的矩形。*/
    ::rectangle(m_x, m_y - 30, m_x + m_w, m_y);
    /*画列*/
    for (size_t i = 0; i < m_cols; i++) {
        line(m_x + i * m_gridW, m_y - 30, m_x + i * m_gridW, m_y);
    }
    /*设置表格风格---为与表头区分，在绘制完成表头的行与列后降低像素点*/
    setlinestyle(PS_SOLID, 1);
    /*分割表头数据*/
    auto headers = split(m_headName);
    /*绘制表头数据*/
    for (size_t i = 0; i < headers.size(); i++) {
        int spaceH = (m_gridW - ::textwidth(headers[i].c_str())) / 2; //水平间距
        int spaceV = (50 - ::textheight(headers[i].c_str())) / 2; //垂直间距
        outtextxy(m_x + i * m_gridW + spaceH, m_y - m_gridH + spaceV, headers[i].c_str());
    }

}

void Table::drawTableGrid() {
    //绘制表头
    drawTableHeader();
    //设置线的颜色
    setlinecolor(BLACK);
    //画横线,画两行有三个横线,所以需要行数加一
    for (size_t i = 0; i < m_rows + 1; i++) {
        line(m_x, m_y + i * m_gridH, m_x + m_cols * m_gridW, m_y + i * m_gridH);
    }
    //画竖线,画四列需要五条竖线,所以也要加+1
    for (size_t i = 0; i < m_cols + 1; i++) {
        line(m_x + i * m_gridW, m_y, m_x + i * m_gridW, m_y + m_rows * m_gridH);
    }

    /*绘制按钮---页数大于1时才绘制*/
    if (m_maxPage > 0) {
        drawTableButton();
    }

}

void Table::drawTableButton() {

   //设置按钮位置
   m_previousBtn.movePosition(m_x, m_h + 100);
   m_nextBtn.movePosition(m_previousBtn.x() + m_previousBtn.width() + 10, m_previousBtn.y());
   m_firstBtn.movePosition(m_nextBtn.x() + m_nextBtn.width() + 10, m_nextBtn.y());
   m_lastBtn.movePosition(m_firstBtn.x() + m_firstBtn.width() + 10, m_firstBtn.y());

   if(m_rows<12){/*小于12就不绘制*/
       return;
   }else{
       //开始绘制按钮
       m_previousBtn.show();
       m_nextBtn.show();
       m_firstBtn.show();
       m_lastBtn.show();

       //显示统计页数
       char str[50] = {0};
       //sprintf_s函数将数据格式化输出到字符串
       sprintf_s(str, "第%d页/共%d页", m_currentPage + 1, m_maxPage + 1);
       outtextxy(m_lastBtn.x() + m_lastBtn.width() + 100, m_lastBtn.y(), str);
   }



}

void Table::drawTableData() {
    /*防止索引越界：Expression: vector subscript out of range
     * ---改变行数*/
    if (m_rows > m_data.size() && m_data.size() != 0) {
        m_rows = m_data.size();
    }

    int beginPos = m_currentPage * m_rows; //数据开始位
    int endPos = m_currentPage * m_rows + m_rows; //数据结束位
    /*没有数据就退出*/
    if (m_data.size() == 0) {
        endPos = 0;
    }
    /*最后一页的处理*/
    if (m_currentPage == m_maxPage) {
        endPos = beginPos + m_extraData;
    }

    for (size_t i = beginPos, r = 0; i < endPos; i++, r++) { //行
        const auto &line_data = split(m_data[i]);
        for (size_t n = 0; n < line_data.size(); n++) { //列
            //使文字水平和垂直方向居中
            int tx = m_x + n * m_gridW + (m_gridW - ::textwidth(line_data[n].c_str())) / 2;
            int ty = m_y + r * m_gridH + 5;
            outtextxy(tx, ty, line_data[n].c_str());
        }
    }
}

void Table::insertData(const std::string &data) {
    m_data.push_back(data);
    updatePage();
}

std::vector<std::string> Table::split(std::string str, char separator) {
    std::vector<std::string> res;
    for (size_t pos = 0; pos != std::string::npos;) { //npos是一个常数，表示size_t的最大值
        //查找指定分割字符的位置
        pos = str.find(separator);
        //根据每个字符串的长度取出字符串
        res.push_back(str.substr(0, pos));
        //把剩下的字符串保存到str,pos跳过前一个字符串,1跳过'\t'
        str = std::string(str.c_str() + pos + 1);
    }
    return res;
}

void Table::updatePage() {
    if (m_rows > m_data.size()) {
        m_maxPage = 0;
        m_extraData = m_data.size(); //只需要一页
    } else {
        m_maxPage = m_data.size() / m_rows;
        m_extraData = m_data.size() % m_rows;
    }
}

void Table::eventTableLoop(const ExMessage &t_msg) {
    m_previousBtn.eventLoop(t_msg);
    m_nextBtn.eventLoop(t_msg);
    m_firstBtn.eventLoop(t_msg);
    m_lastBtn.eventLoop(t_msg);

    if (m_previousBtn.isClicked()) {
        if (m_currentPage != 0) {
            m_currentPage--;
        }
    }
    if (m_nextBtn.isClicked()) {
        if (m_currentPage != m_maxPage) {
            m_currentPage++;
        }
    }
    if (m_firstBtn.isClicked()) {
        m_currentPage = 0;
    }
    if (m_lastBtn.isClicked()) {
        m_currentPage = m_maxPage;
    }
}

void Table::clearTableData() {
    m_data.clear();
    updatePage();
}








